<?php
// +----------------------------------------------------------------------
// | Description: 1
// +----------------------------------------------------------------------
// | Author: orchief
// +----------------------------------------------------------------------
// | Date: 2018-02-02 11:43:01
// +----------------------------------------------------------------------

namespace app\client\controller;

use app\client\model\Member;
use app\client\model\MemberAccount;
use app\client\model\Order;
use app\common\controller\Rest;
use EasyWeChat\Factory;
use think\Log;
use EasyWeChat\Kernel\Exceptions\Exception;
use Payment\Common\PayException;
use Payment\Client\Charge;
use think\Db;

class OrderPays extends Rest
{
    public $modelName = 'OrderPay';
    public $PayConfig;
    public $errorMsg;
    public function _initialize()
    {
        parent::_initialize();
        // $this -> abort(!$this -> isClient, 'Permission denied', 403);
        $this->PayConfig['wechat'] = [
            'app_id' => config('wechat.app_id'),
            'mch_id' => config('wechat.mch_id'),
            'key'    => config('wechat.key'),
            'secret' => config('wechat.secret'),
        ];
    }
    
    public function save()
    {
        $orders = new Order();
        $orInfo = $orders->get($this->param['OrderId']);
        $this->param['PayTotal'] = $orInfo['RealPay'];
        // p($this -> param);
        $orders->startTrans();
        if ($this->param['PayType'] == 1) {
            // 如果采取余额支付
            // 余额扣款
            $members = new Member();
            // p($this -> param['PayTotal']);
            $membersInfo = $members->get($this->param['UserId']);
            // p($membersInfo['Balance']);
            $members->query("UPDATE shop_members SET Balance = Balance - " . $this->param['PayTotal'] . " WHERE Id = " . $this->param['UserId']);

            // 余额记录表生成扣款记录
            $MemberAccount = new MemberAccount();
            $accountData = [
                'UserId' => $this->param['UserId'],
                'Change' => -$this->param['PayTotal'],
                'Remain' => $membersInfo['Balance'] - $this->param['PayTotal'],
                'Type' => '支付订单', // 余额支付
                'Remark' => '',
            ];
            $MemberAccount->createData($accountData);

            // 状态设为 1
            $this->param['Status'] = 1;

            $orders = new Order();
            $date = date("Y-m-d H:i:s");
            $orders->where(['Id' => $this->param['OrderId']])->update(['PayDate' => $date, 'OrderStatus' => 2]);
            $res = self::$model->createData($this->param);
            if ($res) {
                $resData = "支付成功";
            }
        } else if ($this->param['PayType'] == 2) { // 微信jssdk
            try{
                self::$model->data($this->param)->allowField(true)->save();
            }catch(\Exception $e){
                $this -> abort(self::$model -> where(['OrderId' => $this->param['OrderId']]) -> count(), $e -> getMessage());
            }
            $param['OrderId'] = $this->param['OrderId'];
            $jsonData = $this->wechatPay('jssdk', $param); 
            $resData = json_decode($jsonData, true);

        } else if ($this->param['PayType'] == 3) {

            self::$model->data($this->param)->allowField(true)->save();
            $param['OrderId'] = $this->param['OrderId'];
            $jsonData = $this->wechatPay('app', $param);    // 微信app支付
            $resData = json_decode($jsonData, true);
            
        } else if ($this->param['PayType'] == 4) {

            self::$model->data($this->param)->allowField(true)->save();
            $param['OrderId'] = $this->param['OrderId'];
            $resData = $this->alipay('ali_app', $param);    // ali_app支付
        }
        $orders->commit();
        $this->jsonData($resData, self::$model->getError());
    }

    public function wechatPay($type, $param)
    {
        switch ($type) {
            case 'jssdk':
                return $this->jssdk($param); // 调用微信
                break;
            case 'app':
                return $this->wechatappPay($param); // 调用微信
                break;
        }
    }

    /**
     * 微信app支付
     *
     * @return void
     */
    public function wechatappPay($param)
    {
        // 接收订单id
        $this->abort($param['OrderId'], '请输入 OrderId');
        // 获取订单信息
        $OrderPayInfo = self::$model->where(['OrderId' => $param['OrderId']])->find();
        $OrderId = $OrderPayInfo['OrderId'];
        $PayTotal = $OrderPayInfo['PayTotal'];
        // 查询用户openid
        $Member = new Member();
        $userInfo = $Member->get($this->param['UserId']);
        // p($openid);

        $notify = 'client/wechatNotify'; // 回调地址

        // const APPSECRET = '';
        $config = [
            // 必要配置
            'app_id' => $this->PayConfig['wechat']['app_id'],
            'mch_id' => $this->PayConfig['wechat']['mch_id'],
            'key'    => $this->PayConfig['wechat']['key'], // API 密钥
            'secret' =>  $this->PayConfig['wechat']['secret'], // API 密钥

            // 如需使用敏感接口（如退款、发送红包等）需要配置 API 证书路径(登录商户平台下载 API 证书)
            // 'cert_path'          => '/v1/cert/apiclient_cert.pem',      // XXX: 绝对路径！！！！
            // 'key_path'           => '/v1/cert/apiclient_key.pem',       // XXX: 绝对路径！！！！

            'notify_url' => $notify, // 你也可以在下单时单独设置来想覆盖它
        ];
        // echo 11111;
        $app = Factory::payment($config);
        // dump($app);
        $result = $app->order->unify([
            'body' => '商品支付',
            'out_trade_no' => $OrderId,
            'total_fee' => 1,   // 测试期间暂定为一分
            // 'total_fee' => $PayTotal * 100, // 微信这里单位是分
            // 'spbill_create_ip' => '123.12.12.123', // 可选，如不传该参数，SDK 将会自动获取相应 IP 地址
            'trade_type' => 'APP',
        ]);
        // dump($result);
        $this->abort($result['return_code'] != 'FAIL', $result['return_msg']);
        $res = $app->jssdk->appConfig($result['prepay_id']);
        // p($res);
        return $res;
    }
    /**
     * 微信支付测试 公众号支付 调用jssdk
     *
     * @return void
     */
    public function jssdk($param)
    {
        // 接收订单id
        $this->abort($param['OrderId'], '请输入 OrderId');
        // 获取订单信息
        $OrderPayInfo = self::$model->where(['OrderId' => $param['OrderId']])->find();
        $OrderId = $OrderPayInfo['OrderId'];
        $PayTotal = $OrderPayInfo['PayTotal'];
        // 查询用户openid
        $Member = new Member();
        $userInfo = $Member->get($this->param['UserId']);
        if ($userInfo['OpenId']) {
            // 继续支付
            $openid = $userInfo['OpenId'];
        } else {
            // 去获取openid
            $this->abort(false, '登录已失效');
        }

        $notify = 'client/wechatNotify'; // 回调地址

        $config = [
            // 必要配置
            'app_id' => $this->PayConfig['wechat']['app_id'],
            'mch_id' => $this->PayConfig['wechat']['mch_id'],
            'key'    => $this->PayConfig['wechat']['key'], // API 密钥

            // 如需使用敏感接口（如退款、发送红包等）需要配置 API 证书路径(登录商户平台下载 API 证书)
            // 'cert_path'          => '/v1/cert/apiclient_cert.pem',      // XXX: 绝对路径！！！！
            // 'key_path'           => '/v1/cert/apiclient_key.pem',       // XXX: 绝对路径！！！！

            'notify_url' => $notify, // 你也可以在下单时单独设置来想覆盖它
        ];

        $app = Factory::payment($config);
        $result = $app->order->unify([
            'body' => '商品支付',
            'out_trade_no' => $OrderId,
            'total_fee' => $PayTotal * 100, // 微信这里单位是分
            'total_fee' => 1, // 微信这里单位是分
            // 'spbill_create_ip' => '123.12.12.123', // 可选，如不传该参数，SDK 将会自动获取相应 IP 地址
            'trade_type' => 'JSAPI',
            'openid' => $openid,
        ]);
        $this->abort($result['return_code'] != 'FAIL', $result['return_msg']);
        $this->abort($result['result_code'] != 'FAIL', $result['err_code_des']);
        $jssdk = $app->jssdk->bridgeConfig($result['prepay_id']);
        return $jssdk;
    }
    
    /**
     * 退款接口
     *
     * @return void
     */
    public function refund()
    {
        // 接口订单号信息
    }

    /**
     * 支付宝支付
     *
     * @return void
     */
    public function aliPay($type, $param)
    {
        // echo 1;die;
        $config = [
            'use_sandbox'               => false,// 是否使用沙盒模式
            'partner'                   => '2088921393010231',
            'app_id'                    => '2018011401860425',
            'sign_type'                 => 'RSA2',// RSA  RSA2
        
            // 可以填写文件路径，或者密钥字符串  当前字符串是 rsa2 的支付宝公钥(开放平台获取)
            'ali_public_key'            => 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv/kVPk6CbQoHqLfqpGWxj4vfCdMyxMkCgwFTa0MVUA6qePviuvgnYL6qoM+ZgpToFLON2ZGqK5xGpgDuDFXhAEmgXZ1YPUM3L4cKR9PhIRvQtMH8upHBS07NKKh/hm9c7+WK7UlN7K027Fd2JwNk/ttQI5h3PmCH2mMQDxXky5g83wEXr+SmAbQdavLBS0FEhcKbbBIkwSH4+BdxYIaHuzvecrPVtQe/Jy0G6zJpthQ5dIXVpuC6yRLsEKTOFsckT8nSWxzLPTSSU93K0u70e8gz2WWYFaTVyo7IHQO7m2JApxmcQ7kEgY7jMfvHRLgsUAjtIuFa/YDuy/mc1CVxgQIDAQAB',        
            // 可以填写文件路径，或者密钥字符串  我的沙箱模式，rsa与rsa2的私钥相同，为了方便测试
            'rsa_private_key'           => 'MIIEogIBAAKCAQEAz9D1FDnTmNAUHmiO3uepfpetRkuPO+C0HXYdIJEKe9U5dus9zxhzGZhBc2mjKx2JnIxz2g9Dj4yB3U5C4LkOeZFHvbiNGmPG2If6xmBALmfNCtHQzG1Tq8eM+RJZbdABo+fJW0eehfoqlBE7huhY9h1uetgd9ocFwJOSkUGYC19nIfJ84hTRLCv+nqc7TvPlwSyFtXMn1Rtw/98dAx1pm63qkjOVDwmD8UEgj9lEtwzm8i4NqvxGotArcCQkyl5qFhsYk/YfaaeNa8B7N5Vm5Xs+cwPU54vcxVcpB5EVlpLGYuo8OE0/VNGHGiQzPih0mciAu44xpGPRe1k89InswwIDAQABAoIBAHQDaO3TomaKstCO+kNB/IMpVZgKknmQ5bwUtgn6LmoXDK9wf97e/VJqhw9RB8AIC0yTtBEluEeo3s6W5ArkBEqlafFl14/F57n1n2+jR/EgDX1eyDt3ROB+1BovvjDpkCDaQrRsdPjCQYbLX/neN9udbpGxmHiJxBJPz+C7R5AAvuBwozjIAZrCBSxbAmle+tO2Shw1Hpd4x9V1DaNqhkvwHce6bTChENAmO1Si2T7SxIEf5vs1SRkGM+KfKJ2W8z9z21RAqLCjhAgQvkQpiMm3Q4LAfSKJookGGG3+R/xs7PijUwwWCpWEBxBSgvPTB0Q00T7L2vMyQUKZoj70D9ECgYEA57kr6QfLQ9cFXKffXDgEF1BAOou2/aMnL8agnE8fHFRfyAcskqSK0uVEekg/b4Dki7HqKzCPJ/Ek55hPx9Evz32s5VdLXgiRS2QEPvVz9c2XVAjn93KgqbY3V5nWL3L8ZfZsmPEJxYq9twnw3+lfqo8ekoFOJTU3fG/DNqdqlp0CgYEA5ZaYykfz+TXVgeoEPO78puNVaC8Zq4NyswK3NgL2d41tqpV+Z0fJdCYJhy2R7UUwBB9chzLmHRGJI+bsFszSoG2kTA/0dRm97zbSNE2bgiv40JSm4u9y02452f4bBt31cet89EvVBu0depU4cETxWfc2AS2+1v8HBRbROqZ5gt8CgYA6/Zz8GgvZHWg0CliGdYw1Ey0GuoK/V0Wml/5TTKEy6RfpKEpkmpbs0Yj5SGM906ZbGdPvYtFO7cjjXJcS22I8hFX7nJmHOs8iTjf2fy4iKVCZCBtllzznd4fnOTaZpcAzhORomxRNweBCNLmphxPfq8ewrFJkjoOtnhYoV75+0QKBgBBsRWGy4/DfuPYiF0uEjO4jNOjO9bcfIAVOHGzwqVDD/SRGrVQV/oMgdW4GBHpEiLrCw4uoSG2r43N+AUVgQXDYZvhJ6+K0hLGn6kFzi7w0CQhimc2B82TMbbb6RlSna/dKMRYIlqR4MbOjGPZu+BTHakWLUCtw8r+acj0Py4FhAoGAEsRRjlzxgSQMPE4m6LNrMgl3Hrj6oq+ckGzW3lXOL5zL59izmQbkZSG2BC20fdQKVIIGYhyf0UJ3s8rIqiQSJS/mo1s18KZalKQjm4B6CaPLIsGbmBHmYx/vtVt9vQUb39jzYTKDXfAX+119uQIf9MtirnB2Z7hF8W5k5ksSXVg=',

            'limit_pay'                 => [
                //'balance',// 余额
                //'moneyFund',// 余额宝
                //'debitCardExpress',// 	借记卡快捷
                //'creditCard',//信用卡
                //'creditCardExpress',// 信用卡快捷
                //'creditCardCartoon',//信用卡卡通
                //'credit_group',// 信用支付类型（包含信用卡卡通、信用卡快捷、花呗、花呗分期）
            ],// 用户不可用指定渠道支付当有多个渠道时用“,”分隔
        
            // 与业务相关参数
            'notify_url'                => 'http://pstsc.pstech360.com',
            'return_url'                => 'http://pstsc.pstech360.com',
        
            'return_raw'                => false,// 在处理回调时，是否直接返回原始数据，默认为 true
        ];

        $channel = $type;
        $payData = [
            'body' => '一个苹果',
            'subject' => '牛逼公司--付款吧',
            'order_no' => 'NB12312355',
            'timeout_express' => '1489241888',
            'amount' => '100',
            'return_param' => 'buy some',
            //'qr_mod' => '',  // 这个参数建议默认就好，不设置
            'paymethod' => 'creditPay',
        ];

        try {
            $payUrl = Charge::run($channel, $config, $payData);
        } catch (PayException $e) {
            // 异常处理
            $this -> abort(false,  $e -> getMessage());
        }

        // p($payUrl);
        return $payUrl;
    }

    /**
     * 主动查询订单支付情况 (双保险防止出错)
     *
     * @return void
     */
    public function queryOrder()
    {
        $orderId = $this -> param['OrderId'];

        $config = [
            'app_id' => $this->PayConfig['wechat']['app_id'],
            'secret'    => $this->PayConfig['wechat']['secret'], 
            'mch_id' => $this->PayConfig['wechat']['mch_id'],
            'key'    => $this->PayConfig['wechat']['key'], 
        ];

        $app = Factory::payment($config);

        $res = $app->order->queryByOutTradeNumber($orderId);

        if($res['trade_state'] === 'SUCCESS'){
            // 直接修改数据库该订单状态
            self::$model -> where(['OrderId' => $orderId]) 
            -> update(['Status' => 1, 'transaction_id' => $res['transaction_id'], 'EndDate' => date("Y-m-d H:i:s")]);
            $this -> jsonData('支付成功!');
            $sql = "UPDATE shop_members SET OrderStatusOne = OrderStatusOne - 1, OrderStatusTwo = OrderStatusTwo + 1 WHERE Id = ".$this->param['UserId'];
            Db::startTrans();
            try{
                Db::query($sql);
                $this -> cashBack($orderId);
                Db::commit();
            }catch(\Exception $e){
                Db::rollback();
                $this -> abort(false, $e -> getMessage());
            }
        }else{
            self::$model -> where(['OrderId' => $orderId])
            -> update(['ErrMsg' => $res['err_code_des']]);
            $this -> abort(false, $res['err_code_des']);
        }
    }

    /**
     * 用户支付成功之后 对其上级用户的返利结算
     *
     * @return void
     */
    public function cashBack($orderId)
    {
        // 查询出该订单设计到的商品
        $items = Db::table('shop_orders_items') -> where(['OrderId'  => $orderId]) -> field('SkuId') -> select();
        foreach($items as $k => $v){
            $skuids[] =  $v['SkuId'];
        }
        $skuItems = Db::table('shop_goods_sku') -> where('Id', 'in', $skuids) -> select();
        foreach($skuItems as $k => $v)
        {
            dump($v);
            $this -> do_cashBack($v);
        }
    }

    public function do_cashBack($skuItem)
    {
        // 一阶父级11
        $ReferUserId = Db::table('shop_members') -> where(['Id' => $this -> param['UserId']]) -> field('ReferUserId') -> find()['ReferUserId'];
        
        $FirstInfo = Db::table('shop_members') -> where(['Id' => $ReferUserId]) -> find();
        
        if(!$FirstInfo){
            return; // 推荐人不存在不继续返现
        }
        $this -> addAccountRecord($FirstInfo, $skuItem['CashBack1']);    // 推荐人存在继续执行

        // 二阶父级
        $SecondInfo = Db::table('shop_members') -> where(['Id' => $FirstInfo['ReferUserId']]) -> find();
        if(!$SecondInfo){
            return; // 推荐人不存在不继续返现
        }
        $this -> addAccountRecord($SecondInfo, $skuItem['CashBack2']);    // 推荐人存在继续执行

        // 三阶父级
        $ThirdInfo = Db::table('shop_members') -> where(['Id' => $SecondInfo['ReferUserId']]) -> find();
        if(!$ThirdInfo){
            return; // 推荐人不存在不继续返现
        }
        $this -> addAccountRecord($ThirdInfo, $skuItem['CashBack3']);    // 推荐人存在继续执行
    }

    /**
     * 修改账户余额 并新增记录
     *
     * @return void
     */
    public function addAccountRecord($FirstInfo, $CashBack)
    {
        $ramain = $FirstInfo['Balance'] + $CashBack;
        Db::table('shop_members') -> where(['Id' => $FirstInfo['Id']]) -> update(['Balance' => $ramain]);
        $data['UserId'] = $FirstInfo['Id'];
        $data['Change'] = $CashBack;
        $data['Remain'] = $ramain;
        $data['Type']   = '推荐奖励';
        Db::table('shop_members_account') -> insert($data);
    }


    /**
     * 微信回调地址
     *
     * @return void
     */
    public function wechatNotify()
    {
        Log::init([
            'type'  =>  'File',
            'path'  =>  ROOT_PATH.'/runtime/wechatPay/'
        ]);
        Log::record('微信回调');
        $config = [
            // 必要配置
            'app_id' => $this->PayConfig['wechat']['app_id'],
            'mch_id' => $this->PayConfig['wechat']['mch_id'],
            'key'    => $this->PayConfig['wechat']['key'], // API 密钥

            // 如需使用敏感接口（如退款、发送红包等）需要配置 API 证书路径(登录商户平台下载 API 证书)
            // 'cert_path'          => '/v1/cert/apiclient_cert.pem',      // XXX: 绝对路径！！！！
            // 'key_path'           => '/v1/cert/apiclient_key.pem',       // XXX: 绝对路径！！！！
        ];

        $app = Factory::payment($config);
        $response = $app->handlePaidNotify(function ($message, $fail) {
            // 你的逻辑
            // Log::save(['message' => $message]);
            Log::record($message);
            return true;
            // 或者错误消息
            // $fail('Order not exists.');
        });

        $response->send(); // Laravel 里请使用：return $response;
    }

    public function wxConfig()
    {
        $config = [
            // 必要配置
            'app_id' => $this->PayConfig['wechat']['app_id'],
            'mch_id' => $this->PayConfig['wechat']['mch_id'],
            'key'    => $this->PayConfig['wechat']['key'], 
            'secret' => $this->PayConfig['wechat']['secret']

            // 如需使用敏感接口（如退款、发送红包等）需要配置 API 证书路径(登录商户平台下载 API 证书)
            // 'cert_path'          => '/v1/cert/apiclient_cert.pem',      // XXX: 绝对路径！！！！
            // 'key_path'           => '/v1/cert/apiclient_key.pem',       // XXX: 绝对路径！！！！
        ];
        $app = Factory::payment($config);
        $APIs = ['chooseWXPay', 'onMenuShareWeibo'];
        $url = $this -> param['configUrl'];
        // $url = 'http://pstsc.pstech360.com/wx/index.html';
        $app->jssdk->setUrl($url);
        $res = $app->jssdk->buildConfig($APIs, $debug = false, $beta = false, $json = true);
        $resArr = json_decode($res, true);
        // unset($resArr['url']);\
        // dump($resArr);
        // dump($app->jssdk -> getTicket());
        $this -> jsonData($resArr);
    }
}
